﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;

using MonPocGarage.ArmyContracts;
using MonPocGarage.ArmyContracts.Common;
using MonPocGarage.ArmyContracts.Common.Abilities;
using MonPocGarage.ArmyContracts.Common.Enums;
using MonPocGarage.Common.Extensions;
using MonPocGarage.Common.Logging;

namespace MonPocGarage.ArmyData.Builders
{
    internal static class BuildMonsterList
    {
        internal static List<Monster> Build()
        {
            List<Monster> monsters = new List<Monster>();
            List<IAbility> abilities = BuildAbilityList.GetAbilityList();
            XmlDocument xDoc = new XmlDocument();
            try
            {
                foreach (string file in Directory.EnumerateFiles(Environment.CurrentDirectory + "/Data/Monsters"))
                {
                    xDoc.Load(file);
                    foreach (XmlNode xNode in xDoc.SelectNodes("Monsters/Monster"))
                    {
                        Monster mappedMonster = new Monster
                                                    {
                                                        MonsterName = xNode.SelectSingleNode("Name").InnerText,
                                                        Agenda = xNode.SelectSingleNode("Agenda").InnerText.ToEnumValue<Agenda>(),
                                                        EnergyType = xNode.SelectSingleNode("EnergyType").InnerText.ToEnumValue<EnergyType>(),
                                                        Faction = xNode.SelectSingleNode("Faction").InnerText.ToEnumValue<Faction>(),
                                                        MonsterType = xNode.SelectSingleNode("MonsterType").InnerText.ToEnumValue<MonsterType>(),
                                                        MonsterFamily = xNode.SelectSingleNode("MonsterFamily").InnerText,
                                                        Health = Convert.ToInt32(xNode.SelectSingleNode("Health").InnerText),
                                                        HyperCost = Convert.ToInt32(xNode.SelectSingleNode("HyperCost").InnerText),
                                                        Power = Mappers.MapPowerStat(xNode.SelectSingleNode("PowerStat")),
                                                        Stats = new StatBlock
                                                                    {
                                                                        Blast = Mappers.MapBlastStat(xNode.SelectSingleNode("Stats/Blast")),
                                                                        Brawl = Mappers.MapBrawlStat(xNode.SelectSingleNode("Stats/Brawl")),
                                                                        Defense = Convert.ToInt32(xNode.SelectSingleNode("Stats/Defense").InnerText),
                                                                        Speed = Convert.ToInt32(xNode.SelectSingleNode("Stats/Speed").InnerText)
                                                                    },
                                                        Abilities = new List<IAbility>()
                                                    };
                        foreach (XmlNode ability in xNode.SelectNodes("Abilities/Ability/AbilityID"))
                        {
                            IAbility mappedAbility = abilities.Where(a => a.AbilityID == ability.InnerText).FirstOrDefault();
                            if (ability.Attributes["color"] != null)
                            {
                                mappedAbility.ChangeColor(ability.Attributes["color"].Value.ToEnumValue<AbilityColor>());
                            }
                            if (ability.NextSibling != null && mappedAbility.AbilityType == AbilityType.Trigger)
                            {
                                ((Trigger) mappedAbility).ChangeAttackType(ability.NextSibling.InnerText.ToEnumValue<AttackType>());
                            }
                            mappedMonster.Abilities.Add((IAbility)mappedAbility.Clone());
                        }
                        monsters.Add((Monster)mappedMonster.Clone());
                    }
                }
            }
            catch (Exception ex)
            {
                LogHandler.LogException("Unable to parse a monster", ex, MessageLevel.ERROR);
            }
            return monsters;
        }
    }
}
